home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
src
/
lisp.h
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-09
|
12KB
|
409 lines
/* lisp.h -- Data structures/objects for Lisp
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _LISP_H
#define _LISP_H
#ifndef _VALUE_H
# include "value.h"
#endif
/*
* These numbers weren't just plucked from the air, they make the blocks
* of objects fit as close as possible into powers of 2 sized blocks.
*/
#define CONSBLK_SIZE 682
#define SYMBOLBLK_SIZE 170
#define NUMBERBLK_SIZE 127
#define LPOSBLK_SIZE 170
#define OBSIZE 509
enum ValueType
{
/* Static strings are C string constants, use the macro MKSTR to make
them from a normal string constant. */
V_StaticString = 0,
V_DynamicString,
V_Number,
#define V_Char V_Number
V_Cons,
V_Vector,
V_Symbol,
V_Mark,
V_Pos,
/* SUBR with one argument, this arg is new value of variable to set the
var, or NULL to make it return the variable's value. */
V_Var,
V_Subr0,
V_Subr1,
V_Subr2,
V_Subr3,
V_Subr4,
V_Subr5,
V_SubrN,
V_SF,
V_Buffer,
#define V_TX V_Buffer
V_Window,
V_File,
V_Process,
V_GlyphTable,
V_Void
};
#define VAL(x) ((VALUE)(x))
#define VPTR(v) (v)
#define VSTRING(v) ((String *)(v))
#define VSTR(v) (&VSTRING(v)->str_Mem[1])
#define VNUMBER(v) ((Number *)(v))
#define VNUM(v) (VNUMBER(v)->num_Data.number)
#define VCHAR(v) VNUM(v)
#define VCONS(v) ((Cons *)(v))
#define VCAR(v) (VCONS(v)->cn_Car)
#define VCDR(v) (VCONS(v)->cn_Cdr)
#define VVECT(v) ((Vector *)(v))
#define VVECTI(v,i) (VVECT(v)->vc_Array[(i)])
#define VSYM(v) ((Symbol *)(v))
#define VMARK(v) ((Mark *)(v))
#define VLPOS(v) ((LPos *)(v))
#define VPOS(v) (VLPOS(v)->lp_Data.pos)
#define VXSUBR(v) ((XSubr *)(v))
#define VSUBR(v) ((Subr *)(v))
#define VSUBR0FUN(v) (VSUBR(v)->subr_Fun.fun0)
#define VSUBR1FUN(v) (VSUBR(v)->subr_Fun.fun1)
#define VSUBR2FUN(v) (VSUBR(v)->subr_Fun.fun2)
#define VSUBR3FUN(v) (VSUBR(v)->subr_Fun.fun3)
#define VSUBR4FUN(v) (VSUBR(v)->subr_Fun.fun4)
#define VSUBR5FUN(v) (VSUBR(v)->subr_Fun.fun5)
#define VSUBRNFUN(v) (VSUBR(v)->subr_Fun.fun1)
#define VSFFUN(v) (VSUBR(v)->subr_Fun.fun1)
#define VVARFUN(v) (VSUBR(v)->subr_Fun.fun1)
#define VTX(v) ((TX *)(v))
#define VBUFFER(v) VTX(v)
#define VFILE(v) ((LFile *)(v))
#define VPROC(v) ((struct Proc *)(v))
#define VWIN(v) ((VW *)(v))
#define VGLYPHTAB(v) ((GlyphTable *)(v))
#define VTYPE(v) ((v)->type)
#define VTYPEP(v,t) (VTYPE(v) == (t))
#define NILP(v) ((v) == sym_nil)
#define STRINGP(v) (VTYPEP(v, V_StaticString) || VTYPEP(v, V_DynamicString))
#define NUMBERP(v) VTYPEP(v, V_Number)
#define CHARP(v) NUMBERP(v)
#define CONSP(v) VTYPEP(v, V_Cons)
#define VECTORP(v) VTYPEP(v, V_Vector)
#define SYMBOLP(v) VTYPEP(v, V_Symbol)
#define BUFFERP(v) VTYPEP(v, V_Buffer)
#define POSP(v) VTYPEP(v, V_Pos)
#define MARKP(v) VTYPEP(v, V_Mark)
#define FILEP(v) VTYPEP(v, V_File)
#define PROCESSP(v) VTYPEP(v, V_Process)
#define WINDOWP(v) (VTYPEP(v, V_Window) && VWIN(v)->vw_Window)
#define GLYPHTABP(v) VTYPEP(v, V_GlyphTable)
#define VOIDP(v) VTYPEP(v, V_Void)
#define GC_MARK_BIT 0x80
#define GC_MARK(v) (VTYPE(v) & GC_MARK_BIT)
#define GC_MARKEDP(v) (GC_MARK(v) != 0)
#define GC_SET(v) (VTYPE(v) |= GC_MARK_BIT)
#define GC_CLR(v) (VTYPE(v) &= ~GC_MARK_BIT)
#define MARKVAL(v) do { if((v) && !GC_MARKEDP(v)) mark_value(v); } while(0)
typedef struct ValClass {
/* compares two values, rc is similar to strcmp() */
int (*vc_Cmp)(VALUE val1, VALUE val2);
/* prints a textual representation of the object, not necessarily in
a read'able format */
void (*vc_Princ)(VALUE stream, VALUE obj);
/* prints a textual representation of the object, if possible in
a read'able format */
void (*vc_Print)(VALUE stream, VALUE obj);
/* this is the name of the type */
VALUE vc_Name;
} ValClass;
/* The following is an array of VALCLASS structs, the array index corresponds
to the VTF_* numbers */
extern ValClass ValueClasses[];
/* These are also defined as functions (lower-case'd names)... */
#define VALUE_CMP(v1,v2) ValueClasses[VTYPE(v1)].vc_Cmp(v1,v2)
#define PRINC_VAL(s,v) ValueClasses[VTYPE(v)].vc_Princ(s,v)
#define PRINT_VAL(s,v) ValueClasses[VTYPE(v)].vc_Print(s,v)
/* ...except these which aren't. */
#define VALNAME(v) (ValueClasses[VTYPE(v)].vc_Name)
/* String data types. the `String' type is what a VALUE points to, if
the string is dynamic it gets a length field in the word before the
String struct proper. */
typedef struct {
/* str_Mem[0] is type, str_Mem[1->N] is data. */
u_char str_Mem[1];
} String;
typedef struct {
int ds_Length;
u_char ds_Mem[1];
} DynamicString;
#define DSTR_SIZE(s) (sizeof(int) + 1 + (s))
/* Get the beginning of a DynamicString from a String. */
#define DSTRING_HDR(s) ((DynamicString *)(((char *)(s)) - sizeof(int)))
/* Make a static string from a normal C string constant, ie,
MKSTR("foo") -> "\0foo" */
#define MKSTR(s) (VAL(("\0" s)))
/* Get the beginning of the String struct from a (char *) */
#define STRING_HDR(s) ((String *)(((char *)(s))-1))
/* Find the length of this String. */
#define STRING_LEN(s) \
(VTYPEP(s, V_DynamicString) ? (DSTRING_HDR(s)->ds_Length) : strlen(VSTR(s)))
/* True if this string may be written to; generally V_StaticString types
are made from C string-constants and usually in read-only storage. */
#define STRING_WRITEABLE_P(s) (!VTYPEP(s, V_StaticString))
/* Number type. Generally a 32-bit signed integer. */
typedef struct _Number {
u_char num_Type;
union {
long number;
struct _Number *next;
} num_Data;
} Number;
typedef struct _NumberBlk {
struct _NumberBlk *nb_Next;
Number nb_Numbers[NUMBERBLK_SIZE];
} NumberBlk;
/* Cons-cell, a pair of VALUEs, used amongst other things to construct
singly-linked lists (chained through the cdr, last pointer is nil). */
typedef struct {
u_char cn_Type;
VALUE cn_Car;
VALUE cn_Cdr;
} Cons;
typedef struct _ConsBlk {
struct _ConsBlk *cb_Next;
Cons cb_Cons[CONSBLK_SIZE];
} ConsBlk;
/* Vector of VALUEs. */
typedef struct _Vector {
u_char vc_Type;
struct _Vector *vc_Next;
int vc_Size;
VALUE vc_Array[0];
} Vector;
#define VECT_SIZE(s) ((sizeof(VALUE) * (s)) + sizeof(Vector))
/* Symbol object, each symbol has 4 basic attributes, a name, its value
as a variable, its value as a function and a property-list.
Symbols are generally stored in hash tables (obarray) with collisions
chained from the `sym_Next' field. */
typedef struct _Symbol {
u_char sym_Type;
u_char sym_Flags;
VALUE sym_Next; /* next symbol in obarray bucket */
VALUE sym_Name;
VALUE sym_Value;
VALUE sym_Function;
VALUE sym_PropList;
} Symbol;
#define SF_CONSTANT 1
/* Means that the symbol's value may be in the buffer-local storage, if so
then that occurrence takes precedence. */
#define SF_BUFFER_LOCAL 2
/* This means that setting the value of the symbol always sets the
buffer-local value, even if one doesn't already exist. */
#define SF_SET_BUFFER_LOCAL 4
#define SF_DEBUG 8 /* Break on next lisp form. */
typedef struct _SymbolBlk {
struct _SymbolBlk *sb_Next;
Symbol sb_Symbols[SYMBOLBLK_SIZE];
} SymbolBlk;
/* Lisp version of the POS structure. */
typedef union _LPos {
struct {
u_char type;
struct POS pos;
} lp_Data;
union _LPos *lp_Next;
} LPos;
typedef struct _LPosBlk {
struct _LPosBlk *lb_Next;
LPos lb_Pos[LPOSBLK_SIZE];
} LPosBlk;
/* A file object. */
typedef struct _LFile {
u_char lf_Type;
u_char lf_Flags;
struct _LFile *lf_Next;
VALUE lf_Name;
FILE *lf_File;
} LFile;
#define LFF_DONT_CLOSE 1
/* C subroutine, can take from zero to five arguments. */
typedef struct {
u_char subr_Type;
union {
VALUE (*fun0)(void);
VALUE (*fun1)(VALUE);
VALUE (*fun2)(VALUE, VALUE);
VALUE (*fun3)(VALUE, VALUE, VALUE);
VALUE (*fun4)(VALUE, VALUE, VALUE, VALUE);
VALUE (*fun5)(VALUE, VALUE, VALUE, VALUE, VALUE);
} subr_Fun;
VALUE subr_Name;
int subr_DocIndex;
VALUE subr_IntSpec;
} Subr;
typedef struct {
u_char subr_Type;
void *subr_Fun;
VALUE subr_Name;
int subr_DocIndex;
VALUE subr_IntSpec;
} XSubr;
#define LIST_1(v1) cmd_cons(v1, sym_nil)
#define LIST_2(v1,v2) cmd_cons(v1, LIST_1(v2))
#define LIST_3(v1,v2,v3) cmd_cons(v1, LIST_2(v2, v3))
#define LIST_4(v1,v2,v3,v4) cmd_cons(v1, LIST_3(v2, v3, v4))
#define LIST_5(v1,v2,v3,v4,v5) cmd_cons(v1, LIST_4(v2, v3, v4, v5))
/* Keeps a backtrace of all lisp functions called. NOT primitives. */
struct LispCall {
struct LispCall *lc_Next;
VALUE lc_Fun;
VALUE lc_Args;
/* t if `lc_Args' is list of *evalled* arguments. */
VALUE lc_ArgsEvalledP;
};
/* A stack of these providing additional entry points for the mark phase of
garbage collection. */
typedef struct _GCVAL {
VALUE *gcv_Value;
struct _GCVAL *gcv_Next;
} GCVAL;
typedef struct _GCVALN {
VALUE *gcv_First;
int gcv_N;
struct _GCVALN *gcv_Next;
} GCVALN;
#define POPGC (gcv_stack = gcv_stack->gcv_Next)
#define PUSHGC(gcv, val) \
do { \
(gcv).gcv_Value = &(val); \
(gcv).gcv_Next = gcv_stack; \
gcv_stack = &(gcv); \
} while(0)
#define POPGCN (gcvn_stack = gcvn_stack->gcv_Next)
#define PUSHGCN(gcv, valp, n) \
do { \
(gcv).gcv_First = (valp); \
(gcv).gcv_N = (n); \
(gcv).gcv_Next = gcvn_stack; \
gcvn_stack = &(gcv); \
} while(0)
/* Macros for defining functions and their SUBR structures. */
#define DEFUN(name,fsym,ssym,args,type,docindex) \
XSubr ssym = { type, fsym, MKSTR(name), docindex, NULL }; \
VALUE fsym args
/* Same as above but with an extra arg -- an interactive-spec string. */
#define DEFUN_INT(name,fsym,ssym,args,type,docindex,interactive) \
XSubr ssym = { type, fsym, MKSTR(name), docindex, MKSTR(interactive) }; \
VALUE fsym args
#define ADD_SUBR(subr) add_subr(&subr)
#define ADD_CONST_NUM(name,num) add_const_num(MKSTR(name), num)
#define INTERN(sym,name) intern_static(&sym, MKSTR(name))
#define DOC_VAR(sym,docIndex) \
cmd_put(sym, sym_variable_documentation, make_number(docIndex))
/* Macros for ensuring an object is of a certain type
ie, to ensure first arg `foo' is a string,
DECLARE1(foo, STRINGP); */
#define DECLARE(n,x,t) \
do { \
if(! t(x)) \
{ \
signal_arg_error(x, n); \
return(NULL); \
} \
} while(0)
#define DECLARE1(x,t) DECLARE(1,x,t)
#define DECLARE2(x,t) DECLARE(2,x,t)
#define DECLARE3(x,t) DECLARE(3,x,t)
#define DECLARE4(x,t) DECLARE(4,x,t)
#define DECLARE5(x,t) DECLARE(5,x,t)
#define ARG1 (find_member_by_index(args, 1))
#define ARG2 (find_member_by_index(args, 2))
#define ARG3 (find_member_by_index(args, 3))
#define ARG4 (find_member_by_index(args, 4))
#define ARG(n) (find_member_by_index(args, n))
/* Macros for interrupt handling */
#ifndef TEST_INT
# define TEST_INT do { ; } while(0)
#endif
#define INT_P (throw_value != NULL)
#endif /* _LISP_H */